// -*-mode:c++; coding:gb18030-*-

#ifndef _GDRIVE_STR_UTIL_H_
#define _GDRIVE_STR_UTIL_H_

#include <string>
#include <sstream>

#include "platform.h"

#ifdef GDRIVE_PLATFORM_LINUX
#	if __GNUC__ >= 4 and __GNUC_MINOR__ >= 3
#		include <backward/hash_fun.h>
#	else
#		include <ext/hash_fun.h>
#	endif

namespace __gnu_cxx
{
        template<> 
        struct hash<std::string>
        {
                std::size_t operator()(const std::string &__s) const {
                        return __stl_hash_string(__s.c_str());
                }
        };
} // namespace __gnu_cxx
#endif


namespace gdrive
{

        extern
        const int hex_rmap[];

        inline
        int unhex_char(char c)
        {
                return hex_rmap[ c & 0x7F ];
        }

        inline
        int unhex_char(char hx, char lx)
        {
                return (unhex_char(hx) << 4 | unhex_char(lx));
        }

        inline
        std::string unhex_string(const char *hex, std::size_t size)
        {
                std::string bin;
                for(std::size_t i=0; i+1<size; i+=2)
                {
                        bin += static_cast<char>(unhex_char(hex[i], hex[i+1]));
                }
                return bin;
        }
                
        inline
        std::string unhex_string(const std::string &hex)
        {
                return unhex_string(hex.data(), hex.size());
        }

        inline
        std::string hex_string(const char *str, std::size_t size) 
        {
                static const char hex_digit[] = "0123456789ABCDEF";
                std::ostringstream out;
                for(std::size_t i = 0; i < size; ++i)
                {
                        out << (hex_digit[(str[i] >> 4) & 0x0F])
                            << (hex_digit[str[i] & 0x0F]);
                }
                return out.str();
        }

        inline
        std::string hex_string(const std::string str)
        {
                return hex_string(str.data(), str.size());
        }

} /* namespace gdrive */

#endif  // _GDRIVE_STR_UTIL_H_
